using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;

namespace WpfApp_ChenxiConsole.TCP
{
    /// <summary>
    /// TCP服务器管理器，负责监听端口、管理客户端、消息收发等
    /// </summary>
    public class TcpServerManager
    {
        private TcpListener? listener;
        private readonly List<TcpClient> clients = new();
        private CancellationTokenSource? cts;
        private readonly Dispatcher dispatcher;
        private readonly Action<string, string> onMessageReceived;
        private readonly Action<string> onClientConnected;
        private readonly Action<string> onClientDisconnected;
        private readonly Action<Brush> onUpdateServerStatusColor;

        public TcpServerManager(
            Dispatcher dispatcher,
            Action<string, string> onMessageReceived,
            Action<string> onClientConnected,
            Action<string> onClientDisconnected,
            Action<Brush> onUpdateServerStatusColor)
        {
            this.dispatcher = dispatcher;
            this.onMessageReceived = onMessageReceived;
            this.onClientConnected = onClientConnected;
            this.onClientDisconnected = onClientDisconnected;
            this.onUpdateServerStatusColor = onUpdateServerStatusColor;
        }

        /// <summary>
    /// 启动服务器监听
    /// </summary>
    public async Task<bool> StartAsync(int port, int encodingCodePage = 65001)
    {
        try
        {
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            cts = new CancellationTokenSource();
            onUpdateServerStatusColor(Brushes.Green);
            // 启动接受客户端连接的异步任务，但不等待它完成
            _ = AcceptClientsAsync(encodingCodePage, cts.Token);
            
            // 添加await以避免CS1998警告，使方法成为真正的异步方法
            await Task.Yield();
            return true;
        }
        catch (Exception ex)
        {
            onMessageReceived($"启动服务器失败：{ex.Message}", "错误");
            return false;
        }
    }

        /// <summary>
        /// 停止服务器监听
        /// </summary>
        public void Stop()
        {
            try
            {
                cts?.Cancel();
                listener?.Stop();
                lock (clients)
                {
                    foreach (var client in clients)
                    {
                        client.Close();
                    }
                    clients.Clear();
                }
                onUpdateServerStatusColor(Brushes.Transparent);
            }
            catch (Exception ex)
            {
                onMessageReceived($"停止服务器失败：{ex.Message}", "错误");
            }
        }

        /// <summary>
        /// 接收客户端连接
        /// </summary>
        private async Task AcceptClientsAsync(int encodingCodePage, CancellationToken token)
        {
            while (!token.IsCancellationRequested && listener != null)
            {
                try
                {
                    var client = await listener.AcceptTcpClientAsync(token);
                    lock (clients)
                    {
                        clients.Add(client);
                    }
                    string clientInfo = client.Client.RemoteEndPoint?.ToString() ?? "未知客户端";
                    dispatcher.Invoke(() => onClientConnected(clientInfo));
                    _ = ReceiveMessagesAsync(client, clientInfo, encodingCodePage, token);
                }
                catch (Exception)
                {
                    // 监听被停止时会抛异常，忽略
                    break;
                }
            }
        }

        /// <summary>
        /// 接收单个客户端消息
        /// </summary>
        private async Task ReceiveMessagesAsync(TcpClient client, string clientInfo, int encodingCodePage, CancellationToken token)
        {
            try
            {
                var stream = client.GetStream();
                byte[] buffer = new byte[1024];
                int bytesRead;
                while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
                {
                    string message = Encoding.GetEncoding(encodingCodePage).GetString(buffer, 0, bytesRead);
                    
                    // 调用消息过滤器过滤消息
                    MessageFilter.FilterMessage(message);
                    
                    dispatcher.Invoke(() => onMessageReceived(message, $"收<< [{clientInfo}] "));
                }
            }
            catch (Exception ex)
            {
                dispatcher.Invoke(() => onMessageReceived($"客户端[{clientInfo}]断开：{ex.Message}", "断开"));
            }
            finally
            {
                lock (clients)
                {
                    clients.Remove(client);
                }
                dispatcher.Invoke(() => onClientDisconnected(clientInfo));
                client.Close();
            }
        }

        /// <summary>
        /// 群发消息到所有客户端
        /// </summary>
        public async Task<bool> SendToAllAsync(string message, Encoding encoding)
        {
            bool success = true;
            byte[] data = encoding.GetBytes(message);
            
            // 创建客户端列表的副本，避免在异步操作中持有锁
            List<TcpClient> clientsCopy;
            lock (clients)
            {
                clientsCopy = new List<TcpClient>(clients);
            }
            
            // 在锁外部执行异步写操作
            foreach (var client in clientsCopy)
            {
                try
                {
                    var stream = client.GetStream();
                    await stream.WriteAsync(data, 0, data.Length);
                }
                catch
                {
                    success = false;
                }
            }
            
            return success;
        }

        /// <summary>
        /// 发送消息给指定客户端
        /// </summary>
        public async Task<bool> SendToClientAsync(string clientInfo, string message, Encoding encoding)
        {
            byte[] data = encoding.GetBytes(message);
            TcpClient? target = null;
            lock (clients)
            {
                target = clients.Find(c => c.Client.RemoteEndPoint?.ToString() == clientInfo);
            }
            if (target != null)
            {
                try
                {
                    var stream = target.GetStream();
                    await stream.WriteAsync(data, 0, data.Length);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            return false;
        }

        /// <summary>
        /// 获取所有客户端信息
        /// </summary>
        public List<string> GetAllClientInfos()
        {
            lock (clients)
            {
                List<string> infos = new();
                foreach (var c in clients)
                {
                    infos.Add(c.Client.RemoteEndPoint?.ToString() ?? "未知客户端");
                }
                return infos;
            }
        }
    }
}
